package device

import (
	"adai.design/jarvis/common/db"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"errors"
	"github.com/globalsign/mgo/bson"
	"time"
)

// 配件认证注册信息
type Register struct {
	// 设备ID与密钥信息
	Id     string `json:"id"`
	Secret string `json:"secret" bson:"secret"`

	// 基本信息
	Name             string `json:"name,omitempty" bson:"name,omitempty"`
	Manufacturer     string `json:"manufacturer,omitempty" bson:"manufacturer,omitempty"`
	Model            string `json:"model,omitempty" bson:"model,omitempty"`
	SerialNumber     string `json:"serial_number,omitempty" bson:"serial_number,omitempty"`
	FirmwareRevision string `json:"firmware,omitempty" bson:"firmware,omitempty"`

	// 注册时间与激活时间
	RegistrationTime *time.Time `json:"-" bson:"registration_time,omitempty"`
	ActivationTime   *time.Time `json:"-" bson:"activation_time,omitempty"`

	RegistrationTimeStr string `json:"registration_time,omitempty" bson:"-"`
	ActivationTimeStr   string `json:"activation_time,omitempty" bson:"-"`

	// 配件绑定的家庭
	HomeId string `json:"home_id,omitempty" bson:"home_id,omitempty"`
}

func (r *Register) String() string {
	if r.RegistrationTime != nil {
		r.RegistrationTimeStr = r.RegistrationTime.Format("2006-01-02 15:04:05")
	}
	if r.ActivationTime != nil {
		r.ActivationTimeStr = r.ActivationTime.Format("2006-01-02 15:04:05")
	}
	buf, _ := json.Marshal(r)
	return string(buf)
}

func (r *Register) Save() error {
	session, err := db.GetSession()
	if err != nil {
		return err
	}
	defer session.Close()

	collection := session.DB("device").C("register")
	_, err = collection.Upsert(bson.M{"id": r.Id}, r)
	return err
}

// 注册设备管理
type registerManager struct{}

// 通过ID查找设备的注册信息
func (rm *registerManager) findRegisterById(id string) (*Register, error) {
	session, err := db.GetSession()
	if err != nil {
		return nil, err
	}
	defer session.Close()

	collection := session.DB("device").C("register")
	var register *Register
	err = collection.Find(bson.M{"id": id}).One(&register)
	if err != nil {
		return nil, err
	}
	return register, nil
}

// 查找所有账号
func (rm *registerManager) findRegisterAll() ([]*Register, error) {
	session, err := db.GetSession()
	if err != nil {
		return nil, err
	}
	defer session.Close()

	collection := session.DB("device").C("register")
	var registers []*Register
	err = collection.Find(bson.M{}).All(&registers)
	if err != nil {
		return nil, err
	}
	return registers, nil
}

// 注册一个设备
// model: 设备型号，仅支持特定类型的设备注册
func (rm *registerManager) register(model string) (*Register, error) {
	var r Register
	r.Id = db.NewDeviceId()
	var secret [24]byte
	rand.Reader.Read(secret[:])
	r.Secret = base64.StdEncoding.EncodeToString(secret[:])
	r.Model = model
	now := time.Now()
	r.RegistrationTime = &now
	return &r, nil
}

// 设备登录
type loginInfo struct {
	ID   string `json:"uuid"`
	Key  string `json:"key"`
	Date string `json:"date"`
}

func (rm *registerManager) login(data []byte) (*Register, error) {
	var info loginInfo
	err := json.Unmarshal(data, &info)
	if err != nil {
		return nil, err
	}
	if len(info.ID) == 0 || len(info.Key) == 0 {
		return nil, errors.New("invalid-login-information")
	}

	reg, err := rm.findRegisterById(info.ID)
	if reg == nil || err != nil {
		return nil, errors.New("unregister-device")
	}
	if reg.Secret != info.Key {
		return nil, errors.New("invalid-secret-key")
	}
	// 记录激活时间
	if reg.ActivationTime == nil {
		t := time.Now()
		reg.ActivationTime = &t
		reg.Save()
	}
	return reg, nil
}

var registers = registerManager{}
